package com.oswift.utils.common;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

/**
 *
 * IP地址获取及IP地址字符串与整型数值转换类
 *
 * @author zhuou
 * @version C03 2014-7-12
 * @since OSwift GPM V2.0
 */
public class IpUtil
{
    private static final int TWO = 2;

    private static final int THREE = 3;

    private static final int FOUR = 4;

    private static final int EIGHT = 8;

    private static final int ONE_SIX = 16;

    private static final int TWO_FOUR = 24;

    private static final int TWO_FIVE_FIVE = 255;

    private static final int SIX_F = 0x00FFFFFF;

    private static final int FOUR_F = 0x0000FFFF;

    private static final int TWO_F = 0x000000FF;

    /**
     *
     * 获取request的IP
     *
     * @author zhuou
     * @param request
     *            HttpServletRequest
     * @return String
     */
    public static String getRequestIP(HttpServletRequest request)
    {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (StringUtil.isBlank(ipAddress)
                || "unknown".equalsIgnoreCase(ipAddress))
        {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtil.isBlank(ipAddress)
                || "unknown".equalsIgnoreCase(ipAddress))
        {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtil.isBlank(ipAddress)
                || "unknown".equalsIgnoreCase(ipAddress))
        {
            ipAddress = request.getRemoteAddr();
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (!StringUtil.isBlank(ipAddress) && ipAddress.indexOf(',') > 0)
        {
            ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
        }
        return ipAddress;
    }

    /**
     * 判断IP地址是否有效？
     *
     * @param customIP
     *            需要校验的IP地址
     * @return 结果
     */
    public static boolean isValidateIP(String customIP)
    {
        if (StringUtil.isBlank(customIP))
        {
            return false;
        }
        String regex = "^([1-9]|[1-9]\\d|1\\d{2}|2[0-1]\\d|22[0-3]).(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])"
                + ".(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]).(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(customIP);
        return m.matches();
    }

    /**
     * 将ip地字符串转换为十进制整数形式<br>
     *
     * @param strIp
     *            ip地字符串
     * @return 十进制整数
     */
    public static long strToLong(String strIp)
    {
        if (strIp == null)
        {
            return 0;
        }
        long[] ip = new long[FOUR];
        // 先找到IP地址字符串中.的位置
        int position1 = strIp.indexOf(".");
        int position2 = strIp.indexOf(".", position1 + 1);
        int position3 = strIp.indexOf(".", position2 + 1);
        // 将每个.之间的字符串转换成整型
        try
        {
            ip[0] = Long.parseLong(strIp.substring(0, position1));
            ip[1] = Long.parseLong(strIp.substring(position1 + 1, position2));
            ip[TWO] = Long.parseLong(strIp.substring(position2 + 1, position3));
            ip[THREE] = Long.parseLong(strIp.substring(position3 + 1));
        }
        catch (Exception e)
        {
            return 0;
        }

        boolean errorFlag = ip[0] > TWO_FIVE_FIVE || ip[1] > TWO_FIVE_FIVE
                || ip[TWO] > TWO_FIVE_FIVE || ip[THREE] > TWO_FIVE_FIVE;
        if (errorFlag || ip[THREE] < 0 || ip[TWO] < 0 || ip[1] < 0 || ip[0] < 0)
        {
            return 0;
        }
        return (ip[0] << TWO_FOUR) + (ip[1] << ONE_SIX) + (ip[TWO] << EIGHT)
                + ip[THREE];
    }

    /**
     * 将十进制整数转换成ip地址字符串<br>
     *
     * @param longIp
     *            十进制整数
     * @return ip地址字符串
     */
    public static String longToStr(long longIp)
    {
        StringBuffer sb = new StringBuffer("");
        // 直接右移24位
        sb.append(String.valueOf(longIp >>> TWO_FOUR));
        sb.append('.');
        // 将高8位置0，然后右移16位
        sb.append(String.valueOf((longIp & SIX_F) >>> ONE_SIX));
        sb.append('.');
        // 将高16位置0，然后右移8位
        sb.append(String.valueOf((longIp & FOUR_F) >>> EIGHT));
        sb.append('.');
        // 将高24位置0
        sb.append(String.valueOf(longIp & TWO_F));
        boolean errFlag = (longIp >>> TWO_FOUR) > TWO_FIVE_FIVE
                || ((longIp & SIX_F) >>> ONE_SIX) > TWO_FIVE_FIVE
                || ((longIp & FOUR_F) >>> EIGHT) > TWO_FIVE_FIVE;
        errFlag = errFlag || TWO_FIVE_FIVE < (longIp & TWO_F)
                || 0 > (longIp >>> TWO_FOUR)
                || 0 > ((longIp & SIX_F) >>> ONE_SIX);
        if (errFlag || 0 > ((longIp & FOUR_F) >>> EIGHT)
                || 0 > (longIp & TWO_F))
        {
            return null;
        }
        return sb.toString();
    }
}
